import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.List;
import static java.lang.System.out;

/**
*
* @author Colojoara Catalin
*/

public class OClasa {
	/**
	    * @param args the command line arguments
	    */
    public static void main(String... args) {
	try {
		
/**java.lang.Class<?>

Instances of the class Class represent classes and interfaces in a running Java application. 
An enum is a kind of class and an annotation is a kind of interface.
Every array also belongs to a class that is reflected as a Class object that is shared by 
all arrays with the same element type and number of dimensions. 
The primitive Java types (boolean, byte, char, short, int, long, float, and double), 
and the keyword void are also represented as Class objects. 
Class has no public constructor. Instead Class objects are constructed automatically by the 
Java Virtual Machine as classes are loaded and by calls to the defineClass method in the class loader. 
The following example uses a Class object to print the class name of an object: 

     void printClassName(Object obj) {
         System.out.println("The class of " + obj +
                            " is " + obj.getClass().getName());
     }
 
It is also possible to get the Class object for a named type (or for void) using a class 
literal (JLS Section 15.8.2). For example: 

     System.out.println("The name of class Foo is: "+Foo.class.getName());
*/
	    Class<?> c = Class.forName(args[0]);
	    out.format("Class:%n  %s%n%n", c.getCanonicalName());
	    out.format("Modifiers:%n  %s%n%n",
	    		
/** java.lang.reflect.Modifier

The Modifier class provides static methods and constants to decode 
class and member access modifiers. 
The sets of modifiers are represented as integers with distinct 
bit positions representing different modifiers. 
*/    		
	    		
		       Modifier.toString(c.getModifiers()));

/**	    PrintStream java.io.PrintStream.format(String format, Object... args)

	    format
	    public PrintStream format(String format,
	                              Object... args)
	    Writes a formatted string to this output stream using the specified format string and arguments. 
	    The locale always used is the one returned by Locale.getDefault(),
	     regardless of any previous invocations of other formatting methods on this object. 


	    Parameters:
	    format - A format string as described in Format string syntax
	    args - Arguments referenced by the format specifiers in the format string. 
	    If there are more arguments than format specifiers, the extra arguments are ignored. 
	    The number of arguments is variable and may be zero. 
	    The maximum number of arguments is limited by the maximum dimension of a Java array 
	    as defined by the Java Virtual Machine Specification. 
	    The behaviour on a null argument depends on the conversion. 
	   
	    Returns:
	    This output stream 
	    
	    Throws: 
	    IllegalFormatException - If a format string contains an illegal syntax, 
	    a format specifier that is incompatible with the given arguments, 
	    insufficient arguments given the format string, or other illegal conditions. 
	    For specification of all possible formatting errors, 
	    see the Details section of the formatter class specification. 
	    NullPointerException - If the format is null
*/	    
	    
	    
	    out.format("Type Parameters:%n");
	    TypeVariable[] tv = c.getTypeParameters();
	    if (tv.length != 0) {
		out.format("  ");
		for (TypeVariable t : tv)
		    out.format("%s ", t.getName());
		out.format("%n%n");
	    } else {
		out.format("  -- No Type Parameters --%n%n");
	    }

	    out.format("Implemented Interfaces:%n");
	    
/**	    java.lang.reflect.Type

	    Type is the common superinterface for all types in the Java programming language. 
	    These include raw types, parameterized types, array types, type variables and primitive types. 
*/
	    
	    
	    Type[] intfs = c.getGenericInterfaces();
	    if (intfs.length != 0) {
		for (Type intf : intfs)
		    out.format("  %s%n", intf.toString());
		out.format("%n");
	    } else {
		out.format("  -- No Implemented Interfaces --%n%n");
	    }

	    out.format("Inheritance Path:%n");
	    List<Class> l = new ArrayList<Class>();
	    printAncestor(c, l);
	    if (l.size() != 0) {
		for (Class<?> cl : l)
		    out.format("  %s%n", cl.getCanonicalName());
		out.format("%n");
	    } else {
		out.format("  -- No Super Classes --%n%n");
	    }

	    out.format("Annotations:%n");
	    Annotation[] ann = c.getAnnotations();
	    if (ann.length != 0) {
		for (Annotation a : ann)
		    out.format("  %s%n", a.toString());
		out.format("%n");
	    } else {
		out.format("  -- No Annotations --%n%n");
	    }

        
	} catch (ClassNotFoundException x) {
	    x.printStackTrace();
	}
    }

    private static void printAncestor(Class<?> c, List<Class> l) {
  /**
    	Class<? super ?> java.lang.Class.getSuperclass()

    	getSuperclass
    	public Class<? super T> getSuperclass()
    	Returns the Class representing the superclass of the entity 
    	(class, interface, primitive type or void) represented by this Class.
    	 If this Class represents either the Object class, an interface, a primitive type, or void, 
    	 then null is returned. If this object represents an array class then the Class object 
    	 representing the Object class is returned. 

    	Returns:
    	the superclass of the class represented by this object.
   */    	
    	
	Class<?> ancestor = c.getSuperclass();
 	if (ancestor != null) {
	    l.add(ancestor);
	    printAncestor(ancestor, l);
 	}
    }
}
